////////////////////////////////////////////////////////////////////////////////
//File:					UglyApplication.cpp
//Author:				Kesitem
//This file is part of UglyProject.
//See UglyProject.txt for copyright informations.
////////////////////////////////////////////////////////////////////////////////
#include "UglyApplication.h"
#include "UglyLog.h"

namespace Ugly
{

/**
 * \brief Default constructor.
 */
Application::Application()
{
    mQuit = false;
    mWindow = 0;
    mGLContext = 0;
}


/**
 * \brief Destructor.
 */
Application::~Application()
{
    destroy();
}


/**
 * \brief Run the application
 *
 * \return Return code of the application
 */
int Application::run()
{
    gLog << "\n----- Run application -----\n";

    //Create application
    if(!create())
    {
        return -1;
    }

    //Enter main loop
    if(!mainLoop())
    {
        return -2;
    }

    return(0);
}


/**
 * \brief Request end of the application.
 */
void Application::quit()
{
    mQuit = true;
}


/**
 * \brief Init the application.
 *
 * \return False if error.
 */
bool Application::init()
{
    return true;
}


/**
 * \brief Shutdown the application.
 */
void Application::shutdown()
{
}


/**
 * \brief Update the application.
 *
 * \return False if error.
 */
bool Application::update()
{
    return true;
}


/**
 * \brief Create application.
 *
 * \return False if error.
 */
bool Application::create()
{
    gLog << "--- Create application\n";

    //Init SDL
    gLog << "Init SDL...\n";
    if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0)
    {
        gLog << "Error! Application::create: failed to init SDL\n";
        gLog << "   SDL error: " << SDL_GetError() << "\n";
        return false;
    }

    //Get SDL plateform
    gLog << "Plateform: " << SDL_GetPlatform() << "\n";
    gLog << "Video Driver: " << SDL_GetCurrentVideoDriver() << "\n";

    //Create window
    gLog << "Create SDL window...\n";
    mWindow = SDL_CreateWindow("UglyEngine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if(!mWindow)
    {
        gLog << "Error! Application::create: failed to create SDL window\n";
        gLog << "   SDL error: " << SDL_GetError() << "\n";
        return false;
    }

    //Set OpenGL version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    //Set double buffering and zbuffer
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    //Create opengl context
    gLog << "Create OpenGL context (version: 3.2)...\n";
    mGLContext = SDL_GL_CreateContext(mWindow);
    if(!mGLContext)
    {
        gLog << "Error! Application::create: failed to create OpenGL context\n";
        gLog << "   SDL error: " << SDL_GetError() << "\n";
        return false;
    }

    //Init glew
    gLog << "Init OpenGL loader...\n";
    if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
    {
        gLog << "Error! Application::create: failed to init opengl\n";
        return false;
    }

	//Log OpenGL information
	gLog << "OpenGL Informations:\n";
	gLog << "   Vendor: " << (char*)glGetString(GL_VENDOR) << "\n";
	gLog << "   Renderer: " << (char*)glGetString(GL_RENDERER) << "\n";
	gLog << "   Version: " << (char*)glGetString(GL_VERSION) << "\n";
	gLog << "   GLSL: " <<  (char*)glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

    //Init the application
    if(!this->init())
    {
        gLog << "Error! Application::create: failed to init application\n";
        return false;
    }

    return true;
}


/**
 * \brief Destroy application.
 */
void Application::destroy()
{
    gLog << "--- Destroy application\n";

    //Shutdown the application
    this->shutdown();

    //Destroy OpenGL context
    if(mGLContext)
    {
        gLog << "Destroy OpenGL context...\n";
        SDL_GL_DeleteContext(mGLContext);
        mGLContext = 0;
    }

    //Destroy SDL window
    if(mWindow)
    {
        gLog << "Destroy SDL window...\n";
        SDL_DestroyWindow(mWindow);
        mWindow = 0;
    }

    //Shutdown SDL
    gLog << "Quit SDL...\n";
    SDL_Quit();
}


/**
 * \brief Main loop.
 *
 * \return False if error.
 */
bool Application::mainLoop()
{
    gLog << "--- Enter main loop\n";

    //Main loop
    while(!mQuit)
    {
        // Process events
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
        	switch(event.type)
        	{

			//The window is closed
			case SDL_QUIT:
				mQuit = true;
			break;

            //Default: do nothing!
			default:
			break;
        	}
        }

        //Update application
        if(!this->update())
        {
            quit();
        }
        //Update display
        SDL_GL_SwapWindow(mWindow);
    }

    return true;
}

}//namespace Ugly
